﻿using Grow.Json.Text.Parse;
using Grow.Utils.Exceptions;
using System.Text;
using System.Text.Json;

namespace Grow.Json.Text
{
    public class JsonContext : IJsonContext
    {
        private readonly JsonSerializerOptions _jsonSerializerOptions;
        public JsonContext()
        {
            _jsonSerializerOptions = new()
            {
                PropertyNameCaseInsensitive = true,//忽略大小写
                Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,//中文乱码
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,//响应驼峰命名
                AllowTrailingCommas = true,//允许数组末尾多余的逗号
            };
            //基础类型处理通过客户端自定义重载
            _jsonSerializerOptions.Converters.Add(new DateTimeParse());
            _jsonSerializerOptions.Converters.Add(new IntParse());
            _jsonSerializerOptions.Converters.Add(new DoubleParse());
            _jsonSerializerOptions.Converters.Add(new DecimalParse());
            _jsonSerializerOptions.Converters.Add(new FloatParse());
            _jsonSerializerOptions.Converters.Add(new GuidParse());
            _jsonSerializerOptions.Converters.Add(new BoolParse());
        }
        public async Task<T?> DeserializeAsync<T>(string json, CancellationToken cancellationToken = default)
        {
            try
            {
                using MemoryStream memoryStream = new(Encoding.UTF8.GetBytes(json));
                memoryStream.Position = 0;

                return await JsonSerializer.DeserializeAsync<T>(memoryStream, _jsonSerializerOptions, cancellationToken);

            }
            catch (Exception ex)
            {
                throw new GrowBinaryException(ex.Message);
            }
        }

        public async Task<object?> DeserializeAsync(string json, Type type, CancellationToken cancellationToken = default)
        {
            try
            {
                using MemoryStream memoryStream = new(Encoding.UTF8.GetBytes(json));
                memoryStream.Position = 0;

                return await JsonSerializer.DeserializeAsync(memoryStream, type, _jsonSerializerOptions, cancellationToken);

            }
            catch (Exception ex)
            {
                throw new GrowBinaryException(ex.Message);
            }
        }

        public async Task<string> SerializeAsync<T>(T value, CancellationToken cancellationToken = default)
        {
            try
            {
                using MemoryStream memoryStream = new();
                memoryStream.Position = 0;

                await JsonSerializer.SerializeAsync<T>(memoryStream, value, _jsonSerializerOptions, cancellationToken);

                using StreamReader streamReader = new(memoryStream);
                return await streamReader.ReadToEndAsync(cancellationToken);
            }
            catch (Exception ex)
            {
                throw new GrowBinaryException(ex.Message);
            }

        }
    }
}